package com.bifrost.service.impl;

import com.bifrost.constant.InventoryType;
import com.bifrost.constant.OrderItemType;
import com.bifrost.entity.*;
import com.bifrost.exception.InventoryUnavailableException;
import com.bifrost.extension.ExtensionResultHolder;
import com.bifrost.extension.ExtensionResultStatusType;
import com.bifrost.repository.ProductSkuRepository;
import com.bifrost.service.InventoryService;
import com.bifrost.service.ProductSkuService;
import com.bifrost.workflow.inventory.extension.InventoryServiceExtensionManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;

import java.util.*;

/**
 * @author rangf
 * @date 2017/11/15
 */
@Service
public class InventoryServiceImpl implements InventoryService {
    private static final Logger LOG = LoggerFactory.getLogger(InventoryServiceImpl.class);
    @Autowired
    ProductSkuService productSkuService;
    @Autowired
    protected InventoryServiceExtensionManager extensionManager;
    @Autowired
    ProductSkuRepository skuRepository;


    /**
     * 通过Sku获取 库存
     *
     * @param skuId skuId
     * @return Long
     */
    @Override
    public Integer getInventoryBySkuId(Long skuId) {
        return productSkuService.getSkuById(skuId).getQuantityAvailable();
    }

    @Override
    @Transactional(rollbackFor = {InventoryUnavailableException.class})
    public void decrementInventory(ProductSku sku, int quantity) throws InventoryUnavailableException {
        decrementInventory(sku, quantity, null);
    }

    @Override
    @Transactional(rollbackFor = {InventoryUnavailableException.class})
    public void decrementInventory(Map<ProductSku, Integer> skuQuantities) throws InventoryUnavailableException {
        decrementInventory(skuQuantities, null);
    }

    @Override
    @Transactional(rollbackFor = {Exception.class})
    public void incrementInventory(ProductSku sku, int quantity) {
        incrementInventory(sku, quantity, null);
    }

    @Override
    @Transactional(rollbackFor = {Exception.class})
    public void incrementInventory(Map<ProductSku, Integer> skuQuantities) {
        incrementInventory(skuQuantities, null);
    }


    @Override
    @Transactional(rollbackFor = {InventoryUnavailableException.class})
    public void decrementInventory(ProductSku sku, int quantity, Map<String, Object> context) throws InventoryUnavailableException {
        Map<ProductSku, Integer> quantities = new HashMap<ProductSku, Integer>();
        quantities.put(sku, quantity);
        decrementInventory(quantities, context);
    }

    @Override
    @Transactional(rollbackFor = {InventoryUnavailableException.class})
    public void decrementInventory(Map<ProductSku, Integer> skuQuantities, Map<String, Object> context) throws InventoryUnavailableException {
        ExtensionResultStatusType res = extensionManager.getProxy().decrementInventory(skuQuantities, context);
        if (ExtensionResultStatusType.NOT_HANDLED.equals(res)) {
            decrementSku(skuQuantities, context);
        }
    }

    protected void decrementSku(Map<ProductSku, Integer> skuQuantities, Map<String, Object> context) throws InventoryUnavailableException {
        for (Map.Entry<ProductSku, Integer> entry : skuQuantities.entrySet()) {
            ProductSku sku = entry.getKey();
            Integer quantity = entry.getValue();
            if (quantity == null || quantity < 1) {
                throw new IllegalArgumentException("数量 " + quantity + " 无效. 必须大于0.");
            }

            if (checkBasicAvailablility(sku)) {
                if (InventoryType.CHECK_QUANTITY.equals(sku.getInventoryType())) {
                    Integer inventoryAvailable = retrieveQuantityAvailable(sku, context);
                    if (inventoryAvailable == null) {
                        return;
                    }
                    if (inventoryAvailable < quantity) {
                        throw new InventoryUnavailableException(
                                "库存不足.", sku.getSkuId(), quantity, inventoryAvailable);
                    }
                    /*Integer newInventory = inventoryAvailable - quantity;
                    sku.setQuantityAvailable(newInventory);
                    productSkuService.saveSku(sku);*/
                    int updated = skuRepository.decrementInventory(sku.getSkuId(),quantity);
                    if(updated<=0){
                        Long skuId = sku.getSkuId();
                        Integer available = skuRepository.findOne(skuId).getQuantityAvailable();
                        throw new InventoryUnavailableException(
                                "库存不足.", skuId, quantity, available);
                    }

                } else {
                    LOG.info("未扣减库存：sku 标记为ALWAYS_AVAILABLE");
                }
            } else {
                throw new InventoryUnavailableException("sku标记为unavailable", sku.getSkuId(), quantity, 0);
            }
        }
    }

    @Override
    public Integer retrieveQuantityAvailable(ProductSku sku, Map<String, Object> context) {
        return retrieveQuantitiesAvailable(Arrays.asList(sku), context).get(sku);
    }

    @Override
    public Map<ProductSku, Integer> retrieveQuantitiesAvailable(Collection<ProductSku> skus, Map<String, Object> context) {
        ExtensionResultHolder<Map<ProductSku, Integer>> holder = new ExtensionResultHolder<Map<ProductSku, Integer>>();
        ExtensionResultStatusType res = extensionManager.getProxy().retrieveQuantitiesAvailable(skus, context, holder);
        if (ExtensionResultStatusType.NOT_HANDLED.equals(res)) {
            Map<ProductSku, Integer> inventories = new HashMap<>();

            for (ProductSku sku : skus) {
                Integer quantityAvailable = 0;
                if (checkBasicAvailablility(sku)) {
                    String skuInventoryType = sku.getInventoryType();
                    if (InventoryType.CHECK_QUANTITY.equals(skuInventoryType)) {
                        Integer availableQuantity = sku.getQuantityAvailable();
                        if (availableQuantity != null) {
                            quantityAvailable = availableQuantity;
                        }
                    } else if (sku.getInventoryType() == null || InventoryType.ALWAYS_AVAILABLE.equals(skuInventoryType)) {
                        quantityAvailable = null;
                    }
                }
                inventories.put(sku, quantityAvailable);
            }

            return inventories;
        } else {
            return holder.getResult();
        }
    }

    @Override
    public Map<ProductSku, Integer> buildSkuInventoryMap(Order order) {
        HashMap<ProductSku, Integer> skuInventoryMap = new HashMap<ProductSku, Integer>();
        order.getOrderItems().forEach(orderItem -> {
            if (OrderItemType.BASIC.equalsIgnoreCase(orderItem.getOrderItemType())) {
                ProductSku sku = productSkuService.getSkuById(orderItem.getSkuId());
                Integer quantity = skuInventoryMap.get(sku);
                if (quantity == null) {
                    quantity = orderItem.getSkuQuantity();
                } else {
                    quantity += orderItem.getSkuQuantity();
                }
                //团购秒杀
                if(orderItem.isPromoApplied()){
                    skuInventoryMap.put(sku, quantity);
                }else if (InventoryType.CHECK_QUANTITY.equals(sku.getInventoryType())) {
                    skuInventoryMap.put(sku, quantity);
                }
            } else if (OrderItemType.BUNDLE.equalsIgnoreCase(orderItem.getOrderItemType())) {
                ProductSku sku = productSkuService.getSkuById(orderItem.getSkuId());
                //团购秒杀
                if(orderItem.isPromoApplied()){
                    skuInventoryMap.put(sku, orderItem.getSkuQuantity());
                }else{
                    if (InventoryType.CHECK_QUANTITY.equals(sku.getInventoryType())) {
                        // 添加组合sku到map中
                        skuInventoryMap.put(sku, orderItem.getSkuQuantity());
                    }
                    //现在添加绑定的sku
                    List<OrderBundleItem> bundleItems = orderItem.getOrderBundleItems();
                    bundleItems.forEach(bundleItem -> {
                        ProductSku discreteItem = productSkuService.getSkuById(orderItem.getSkuId());
                        if (InventoryType.CHECK_QUANTITY.equals(discreteItem.getInventoryType())) {
                            Integer quantity = skuInventoryMap.get(discreteItem);
                            if (quantity == null) {
                                quantity = (bundleItem.getItemQuantity() * orderItem.getSkuQuantity());
                            } else {
                                quantity += (bundleItem.getItemQuantity() * orderItem.getSkuQuantity());
                            }
                            skuInventoryMap.put(discreteItem, quantity);
                        }
                    });
                }
            } else if (OrderItemType.GIFTWRAP.equalsIgnoreCase(orderItem.getOrderItemType())) {
                ProductSku sku = productSkuService.getSkuById(orderItem.getSkuId());
                if (InventoryType.CHECK_QUANTITY.equals(sku.getInventoryType())) {
                    // 添加item到map
                    skuInventoryMap.put(sku, orderItem.getSkuQuantity());
                }
                //添加item附属礼品到sku
                List<GiftwrapOrderItem> gifts = orderItem.getGiftwrapOrderItems();
                if (gifts != null && !gifts.isEmpty()) {
                    gifts.forEach(gift -> {
                        ProductSku skuGift = gift.getProductSku();
                        if (InventoryType.CHECK_QUANTITY.equalsIgnoreCase(skuGift.getInventoryType())) {
                            skuInventoryMap.put(skuGift, gift.getQuantity());
                        }
                    });
                }
            }
        });
        return skuInventoryMap;
    }

    /**
     * 检查库存是否可用
     *
     * @param sku
     * @return
     */
    @Override
    public boolean checkBasicAvailablility(ProductSku sku) {
        return productSkuService.isAvailable(sku);
    }

    /**
     * 查询基本库存
     *
     * @param sku
     * @return
     */
    @Override
    public boolean checkInventory(ProductSku sku) {
        if (InventoryType.CHECK_QUANTITY.equalsIgnoreCase(sku.getInventoryType())) {
            Integer stock = sku.getQuantityAvailable();
            if (stock == null || stock <= 0) {
                return false;
            }
        } else if (InventoryType.UNAVAILABLE.equalsIgnoreCase(sku.getInventoryType())) {
            return false;
        }
        return true;
    }

    @Override
    @Transactional(rollbackFor = {Exception.class})
    public void incrementInventory(ProductSku sku, int quantity, Map<String, Object> context) {
        Map<ProductSku, Integer> quantities = new HashMap<ProductSku, Integer>();
        quantities.put(sku, quantity);
        incrementInventory(quantities, context);
    }

    @Override
    @Transactional(rollbackFor = {Exception.class})
    public void incrementInventory(Map<ProductSku, Integer> skuQuantities, Map<String, Object> context) {
        ExtensionResultStatusType res = extensionManager.getProxy().incrementInventory(skuQuantities, context);
        if (ExtensionResultStatusType.NOT_HANDLED.equals(res)) {
            incrementSku(skuQuantities, context);
        }
    }

    protected void incrementSku(Map<ProductSku, Integer> skuQuantities, Map<String, Object> context) {
        for (Map.Entry<ProductSku, Integer> entry : skuQuantities.entrySet()) {
            ProductSku sku = entry.getKey();
            Integer quantity = entry.getValue();
            if (quantity == null || quantity < 1) {
                throw new IllegalArgumentException("数量 " + quantity + " 无效. 必须大于0或非空.");
            }
            if (InventoryType.CHECK_QUANTITY.equals(sku.getInventoryType())) {
                Integer currentInventoryAvailable = retrieveQuantityAvailable(sku, context);
                if (currentInventoryAvailable == null) {
                    throw new IllegalArgumentException("当前sku库存为null");
                }
                int updated = skuRepository.incrementInventory(sku.getSkuId(),quantity);
                if(updated<1){
                    throw new RuntimeException("增加库存失败");
                }
                /*int newInventory = currentInventoryAvailable + quantity;
                sku.setQuantityAvailable(newInventory);
                productSkuService.saveSku(sku);*/
            } else {
                LOG.info("为增加库存当前sku库存类型标记为ALWAYS_AVAILABLE");
            }
        }
    }

    /**
     * 查询商品所有库存
     *
     * @param product
     * @return
     */
    @Override
    public Integer retrieveQuantityAvailable(Product product) {
        Assert.notNull(product,"商品不能为空");
        return skuRepository.getProductInventory(product.getProductId());
    }
/**
     *
     * 增加库存
     *
     * @param inventoryToIncrement 待增库存sku
     * @return
     */
 /*   @Override
    @Transactional(rollbackFor =exception.class)
    public void incremetInventory(Map<ProductSku, Integer> inventoryToIncrement) {
        for (ProductSku sku : inventoryToIncrement.keySet()){
            sku.setQuantityAvailable(sku.getQuantityAvailable() + inventoryToIncrement.get(sku));
            productSkuService.saveSku(sku);
        }
    }*/
}
